﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Xml;
using System.Runtime.InteropServices;
using System.Web;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Diagnostics;

namespace TweetsRiot
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        public string IniPath { get; set; }

        [DllImport("KERNEL32.DLL")]
        public static extern uint
          GetPrivateProfileStringA(string lpAppName,
          string lpKeyName, string lpDefault,
          [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpReturnedString, uint nSize,
          string lpFileName);

        [DllImport("KERNEL32.DLL")]
        public static extern uint
          GetPrivateProfileIntA(string lpAppName,
          string lpKeyName,
          int nDefault, string lpFileName);

        [DllImport("KERNEL32.DLL")]
        public static extern uint WritePrivateProfileStringA(
          string lpAppName,
          string lpKeyName,
          string lpString,
          string lpFileName);

        public static string GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, string lpFileName)
        {
            StringBuilder buf = new StringBuilder(1024);
            uint result = GetPrivateProfileStringA(lpAppName, lpKeyName, null, buf, (uint)buf.Capacity, lpFileName);
            return buf.ToString();
        }

        public static void WritePrivateProfileString(string lpAppName, string lpKeyName, string lpString, string lpFileName)
        {
            WritePrivateProfileStringA(lpAppName, lpKeyName, lpString, lpFileName);
        }

        public static uint GetPrivateProfileInt(string lpAppName, string lpKeyName, int nDefault, string lpFileName)
        {
            uint result = GetPrivateProfileIntA(lpAppName, lpKeyName, nDefault, lpFileName);
            return result;
        }

        volatile bool loginFlag = false;
        volatile bool authFlag = false;

        TwitterAccess twitter = new TwitterAccess();
        Dictionary<long, bool> StatusHash = new Dictionary<long, bool>();

#if DEBUG
        protected void OnUpdateListItem(TwitterAccess.StatusItem statusItem)
        {
        }
#endif

        protected void UpdateList()
        {
            try
            {
                ReloadButton.Enabled = false;
                TweetButton.Enabled = false;

                int getCount = (int)GetPrivateProfileInt("TIMELINE", "get_count", 20, IniPath);
                List<TwitterAccess.StatusItem> listItem = twitter.GetStatusesHomeTimeline(getCount);
                int itemIndex = 0;
                foreach (var statusItem in listItem)
                {
                    if (StatusHash.ContainsKey(statusItem.id))
                    {
                        continue;
                    }

                    //bool retweetDuplicate = false;
                    //if (statusItem.retweeted_status && StatusHash.ContainsKey(statusItem.retweeted_status_id))
                    //{
                    //    retweetDuplicate = true;
                    //}

#if DEBUG
                    OnUpdateListItem(statusItem);
#endif

                    ListViewItem item = MessageList.Items.Insert(itemIndex++, "");
                    item.Tag = statusItem;
                    item.SubItems.Add(statusItem.name);
                    item.SubItems.Add(statusItem.text);
                    item.SubItems.Add(statusItem.created_at.ToString("yyyy/MM/dd HH:mm:ss"));
                    StatusHash.Add(statusItem.id, true);
                    if (statusItem.retweeted_status && !StatusHash.ContainsKey(statusItem.retweeted_status_id))
                    {
                        StatusHash.Add(statusItem.retweeted_status_id, true);
                    }
                }

                int max_items = (int)GetPrivateProfileInt("TIMELINE", "max_items", 10000, IniPath);
                if (MessageList.Items.Count > max_items)
                {
                    max_items /= 2;
                    while (MessageList.Items.Count > max_items)
                    {
                        MessageList.Items.RemoveAt(MessageList.Items.Count - 1);
                    }
                }
            }
            finally
            {
                ReloadButton.Enabled = true;
                TweetButton.Enabled = true;
            }
        }

        protected void OnTimer(object sender, EventArgs e)
        {
            if (!loginFlag && authFlag)
            {
                authFlag = false;


                LoginForm form = new LoginForm();
                form.Twitter = twitter;
                form.ShowDialog(this);

                string pin = form.PinText.Text;
                if (pin == "")
                {
                    return;
                }

                string oauth_token_secret = twitter.CallOauthAccessTokenUrl(pin);
                string oauth_token = twitter.OauthToken;

                WritePrivateProfileString("ACCOUNT", "oauth_token", oauth_token, IniPath);
                WritePrivateProfileString("ACCOUNT", "oauth_token_secret", oauth_token_secret, IniPath);

                loginFlag = true;
                BeginInvoke(new EventHandler(delegate { UpdateList(); }));
                return;
            }

            if (loginFlag)
            {
                UpdateList();
            }
        }

        Timer timer = new Timer();

        //TwitterAccess.UserStreamReadEvent UserStreamRead3;
        //void UserStreamRead(object sender, TwitterAccess.UserStreamUserEventArgs e)
        //{
        //    Invoke(UserStreamRead3, new object[]{sender,e});
        //}

        void UserStreamRead2(object sender, TwitterAccess.UserStreamUserEventArgs e)
        {
            try
            {
                ReloadButton.Enabled = false;
                TweetButton.Enabled = false;
                List<TwitterAccess.StatusItem> listItem = new List<TwitterAccess.StatusItem>();

                TwitterAccess.StatusItem item1 = new TwitterAccess.StatusItem();
                item1.text = e.message;
                listItem.Add(item1);

                int itemIndex = 0;
                foreach (var statusItem in listItem)
                {
                    if (StatusHash.ContainsKey(statusItem.id))
                    {
                        continue;
                    }

                    ListViewItem item = MessageList.Items.Insert(itemIndex++, "");
                    item.Tag = statusItem;
                    item.SubItems.Add(statusItem.name);
                    item.SubItems.Add(statusItem.text);
                    item.SubItems.Add(statusItem.created_at.ToString("yyyy/MM/dd HH:mm:ss"));
                    StatusHash.Add(statusItem.id, true);
                }
            }
            finally
            {
                ReloadButton.Enabled = true;
                TweetButton.Enabled = true;
            }
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            IniPath = Path.Combine(Application.StartupPath, Application.ProductName + ".ini");
#if DEBUG
            if (Path.GetFileName(Application.StartupPath).Equals("debug", StringComparison.OrdinalIgnoreCase))
            {
                string IniPathDebug = Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(Application.StartupPath)), Application.ProductName + ".ini");
                if (File.Exists(IniPathDebug))
                {
                    IniPath = IniPathDebug;
                }
            }
#endif

            twitter.ConsumerKey = Properties.Settings.Default.ConsumerKey;
            twitter.ConsumerSecret = Properties.Settings.Default.ConsumerSecret;

            string version = GetPrivateProfileString("COMMON", "version", null, IniPath);
            if (version == "")
            {
                WritePrivateProfileString("COMMON", "version", Application.ProductName + " " + Application.ProductVersion, IniPath);
                WritePrivateProfileString("ACCOUNT", "oauth_token", "", IniPath);
                WritePrivateProfileString("ACCOUNT", "oauth_token_secret", "", IniPath);
            }

            timer.Tick += new EventHandler(OnTimer);
//            timer.Interval = 180 * 1000;
            timer.Interval = (int)GetPrivateProfileInt("TIMELINE", "reload_interval", 1, IniPath) * 60 *  1000;
            timer.Start();


            string oauth_token = GetPrivateProfileString("ACCOUNT", "oauth_token", null, IniPath);
            string oauth_token_secret = GetPrivateProfileString("ACCOUNT", "oauth_token_secret", null, IniPath);
            if (oauth_token == "" || oauth_token_secret == "")
            {
                authFlag = true;
            }
            else
            {
                twitter.OauthToken = oauth_token;
                twitter.OauthTokenSecret = oauth_token_secret;
                TwitterAccess.UserInfo currentUserInfo = twitter.GetAccountVerifyCredentials();
                loginFlag = true;

                //twitter.OnUserStreamRead += UserStreamRead;
                //UserStreamRead3 = UserStreamRead2;
                BeginInvoke(new EventHandler(delegate { UpdateList(); }));
            }

            if (authFlag)
            {
                Show();
                EventHandler OnTimer2 = OnTimer;
                Invoke(OnTimer2, new object[] { this, null });
            }
        }

        private void TweetButton_Click(object sender, EventArgs e)
        {
            if (!loginFlag)
            {
                return;
            }

            string message = MessageText.Text;
            if (message.Length <= 0)
            {
                return;
            }

            try
            {
                twitter.PostStatusesUpdate(message);
            }
            catch (WebException we)
            {
                MessageBox.Show(this, "送信に失敗しました。\n" + we.Message);
                return;
            }
            MessageText.Text = "";
            BeginInvoke(new EventHandler(delegate { UpdateList(); }));

        }

        private void MessageList_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (MessageList.SelectedIndices.Count != 1)
            {
                return;
            }

            int selectedIndex = MessageList.SelectedIndices[0];
            TwitterAccess.StatusItem statusItem = (TwitterAccess.StatusItem)MessageList.Items[selectedIndex].Tag;
            StatusText.Text = statusItem.text;
            UserText.Text = statusItem.name + " (@" + statusItem.screen_name + ")";

            TwitterAccess.UserInfo userInfo = null;
            try
            {
                userInfo = twitter.CallUsersShow(statusItem.user_id);
            }
            catch (WebException)
            {
            }

            if (statusItem.profile_image_url != null)
            {
                HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(statusItem.profile_image_url);

                HttpWebResponse response = null;
                try
                {
                    using (response = (HttpWebResponse)request.GetResponse())
                    {
                        byte[] buf = new byte[response.ContentLength];
                        response.GetResponseStream().Read(buf, 0, buf.Length);
                        MemoryStream mem = new MemoryStream(buf);
                        Image image = Image.FromStream(mem);
                        IconPicture.Image = image;
                    }
                }
                catch (WebException we)
                {
                    HttpWebResponse res = (HttpWebResponse)we.Response;
                    string result = new StreamReader(res.GetResponseStream()).ReadToEnd();
                    //throw we;
                }
                catch (ArgumentException)
                {
                }
            }

        }

        private void ReloadButton_Click(object sender, EventArgs e)
        {
            BeginInvoke(new EventHandler(delegate { UpdateList(); }));
        }

        private void IconPicture_DoubleClick(object sender, EventArgs e)
        {
            if (MessageList.SelectedIndices.Count != 1)
            {
                return;
            }
            int selectedIndex = MessageList.SelectedIndices[0];
            TwitterAccess.StatusItem statusItem = (TwitterAccess.StatusItem)MessageList.Items[selectedIndex].Tag;
            string url = "https://twitter.com/#!/" + statusItem.screen_name + "/";
            Process.Start(url);

        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            twitter.EndUserStreamUser();
            timer.Stop();
        }
    }
}
